package com.alex.activiti.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 官方demo代码
 * PS：接入Activiti7的用户必须具有 ROLE_ACTIVITI_USER 角色，不然会报403 Forbidden异常
 */
@Slf4j
@Configuration
public class SpringSecurityConfiguration {

    /**
     * UserDetailsService是Spring Security中查询用户的接口
     * 使用内存模式创建一些用户供测试使用
     */
    @Bean("myUserDetailsService")
    public UserDetailsService getUserDetailsService() {
        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
        //这里添加用户，后面处理流程时用到的任务负责人，需要添加在这里
        String[][] usersGroupsAndRoles = {
                {"jack", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
                {"rose", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
                {"tom", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
                {"other", "password", "ROLE_ACTIVITI_USER", "GROUP_otherTeam"},
                {"zhangsan", "password", "ROLE_ACTIVITI_USER"},
                {"admin", "password", "ROLE_ACTIVITI_ADMIN"}
        };

        // "ROLE_ACTIVITI_USER"是用户角色，必须具有`ACTIVITI_USER`才能使用Activiti7框架，否则会报403错误
        // "GROUP_activitiTeam"是用户组，即组织架构，`activitiTeam`是组标识
        // 在Activiti7中默认提供了`org.activiti.core.common.spring.identity.ActivitiUserGroupManagerImpl`，
        // 默认是从Collection<? extends GrantedAuthority> authorities中查询角色和组信息，
        // 故此处demo取角色和组放到authorities集合中，也可以模仿ActivitiUserGroupManagerImpl用自定义方式实现对角色和组的管理
        // 不过注意要加上`@Primary`注解，即让Spring容器有限采用此实现类
        for (String[] user : usersGroupsAndRoles) {
            List<String> authoritiesStrings = Arrays.asList(Arrays.copyOfRange(user, 2, user.length));
            log.info("> Registering new user: " + user[0] + " with the following Authorities[" + authoritiesStrings + "]");
            inMemoryUserDetailsManager.createUser(new User(user[0], getPasswordEncoder().encode(user[1]),
                    authoritiesStrings.stream().map(s -> new SimpleGrantedAuthority(s)).collect(Collectors.toList())));
        }

        return inMemoryUserDetailsManager;
    }

    /**
     * 加密策略
     */
    @Bean
    public PasswordEncoder getPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
